package com.xiashitech.agent.instrumentation.spring.controller.apicapture.inst.utils;

import com.xiashitech.agent.dto.UserRequest;
import com.xiashitech.agent.instrumentation.spring.controller.apicapture.cache.ApiCache;
import com.xiashitech.agent.instrumentation.spring.controller.apicapture.inst.ApiGenerate;
import com.xiashitech.agent.utils.JsonUtil;
import com.xiashitech.interfaces.agent.dto.api.*;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.common.AttributesBuilder;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;
import java.util.StringJoiner;

/**
 * 该类与全量api代码有部分重合，但是考虑后续根据请求实时捕获无法从静态代码获取的api信息时，要对该类进行修改，所以不提取公共处理类。
 */
public class GenerateSpanAttrUtil {
    public static void generateSpanAttr(UserRequest userRequest, AttributesBuilder attributesBuilder, Class<?> beanType, Method method) {
        String methodSign = getMethodSign(beanType,method);
        Api api = Api.builder().build();
        if(!ApiCache.cache.containsKey(methodSign)) {
            //添加拦截到的api信息
            api = ApiGenerate.generateApi(userRequest);
            ApiCache.cache.put(methodSign, api);
        } else {
            api = ApiCache.cache.get(methodSign);
        }
        //设置请求路径
        List<Path> paths = api.getPaths();
        if(paths == null || paths.size() == 0) {
            return;
        } else {
            StringJoiner stringJoiner = new StringJoiner(",");
            paths.stream().map(path -> path.getName()).forEach(pathName -> {
                stringJoiner.add(pathName);
            });
            System.out.println(Thread.currentThread().getId() + " T" + System.nanoTime()+ " generateSpanAttr set to span path: " + stringJoiner.toString());
            attributesBuilder.put("xs.api.path",stringJoiner.toString());
        }
        //设置请求方式
        List<HttpMethod> httpMethods = api.getHttpMethods();
        if(httpMethods != null) {
            StringJoiner stringJoiner = new StringJoiner(",");
            httpMethods.stream().map(httpMethod -> httpMethod.getName()).forEach(httpMethodName -> {
                stringJoiner.add(httpMethodName);
            });
            attributesBuilder.put("xs.api.httpMethod",stringJoiner.toString());
        }
        //设置请求Content-Type
        List<Consumes> consumes = api.getConsumes();
        if(consumes != null) {
            StringJoiner stringJoiner = new StringJoiner(",");
            consumes.stream().map(consume -> consume.getName()).forEach(consumeName -> {
                stringJoiner.add(consumeName);
            });
            attributesBuilder.put("xs.api.requestContentType",stringJoiner.toString());
        }
        List<Produces> produces = api.getProduces();
        if(produces != null) {
            StringJoiner stringJoiner = new StringJoiner(",");
            produces.stream().map(produce -> produce.getName()).forEach(produceName -> {
                stringJoiner.add(produceName);
            });
            attributesBuilder.put("xs.api.responseContentType",stringJoiner.toString());
        }
        List<Params> requestParams = api.getRequestParams();
        if(requestParams != null) {
            attributesBuilder.put("xs.api.requestParams", JsonUtil.convertObjectToString(requestParams));
        }
        List<Params> responseParams = api.getResponseParams();
        if(responseParams != null) {
            attributesBuilder.put("xs.api.responseParams",JsonUtil.convertObjectToString(responseParams));
        }
    }

    /**
     * 获取方法标识
     * @param beanType
     * @param method
     * @return
     */
    public static String getMethodSign(Class<?> beanType, Method method) {
        StringBuffer methodSignBuffer = new StringBuffer(beanType.getName());
        methodSignBuffer.append(method.getName());
        for (Parameter parameter : method.getParameters()) {
            methodSignBuffer.append(parameter.getType()).append(parameter.getName());
        }
        String methodSign = methodSignBuffer.toString();
        methodSign.replaceAll("\\s*", "");
        return methodSign;
    }
}
